import tkinter as gui
import threading, time, logging

UP = 1
DOWN = 2
LEFT = 3
RIGHT = 4

class SnakeGUI:

    def __init__(self):
        pass

    def update(self):
        """ 对方块的更新。"""
        pass

    pass


class Snake:
    """
    1. 访问snake的方法都需要上锁Lock。如，add，get，remove。
    """

    def __init__(self):
        self.snake = [[]]  # 所有玩家的信息。
        self.lock = threading.Lock()

    def _decode(self, _data: bytes)-> str:
        """ 这是一个内部方法，只在添加信息的时候被add调用。"""
        return _data.decode('utf-8')
        pass

    def add(self, _data: bytes, addr: tuple):
        """
        接收到数据往里添加。
        当某个时间内所有玩家都提交了数据，把数据保存到snake中,
        并把这些数据同时返回给所有玩家，完成一次贪吃蛇的动画同步。
        """
        data = self._decode(_data)
        pass

    def recv(self, _data: bytes)-> str:
        """ 获取坐标发送给服务器。"""
        data = _data.decode().rsplit(',')
        # if len(data) > 0:
        #     return data[0]
        # else:
        #     return None
        return data[0] or None
        pass

    def send(self):
        """ 当接收到所有玩家的数据后，将数据发送给所有玩家。"""
        pass

    def remove(self, addr: tuple):
        """ 有玩家失败了就删除它的数据。"""
        pass


import socket, random


class SnakeSocket:
    """
    1. send和recv这两个方法都需要一直执行下去。
    """
    state = None
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
    PORT = 8888
    IP = '<broadcast>'
    ADDRESS = (IP, PORT)
    sock.bind(ADDRESS)
    # IP = str(random.random())

    def __init__(self):
        self.snake = Snake()
        self.lock = threading.Lock()
        self.begin = time.time()
        logging.basicConfig(level=logging.DEBUG, format='%(message)s')

        self.send_thread = threading.Thread(target=self.send)
        self.recv_thread = threading.Thread(target=self.recv)
        self.send_thread.start()
        self.recv_thread.start()

        start = time.time()
        while not SnakeSocket.state:
            # print(time.time() - start, SnakeSocket.state)
            if time.time() - start > 3:
                SnakeSocket.state = 'master'
        else:
            print('time out 3 second ' + '=' * 50 + SnakeSocket.state)
        pass

    def send(self):
        """"
        1.发送自己每走一步的位置给服务器。
        2.需要加锁。
        3.如果是服务器需要在一定时间内将所有数据发送给客户端。
        """
        # while 1:
        # with self.lock:
            # print('lock')
        logging.info('send start ' + ', state is : ' + str(SnakeSocket.state))
        if SnakeSocket.state is None:
            for _ in range(3):
                logging.warning('sendto 1')
                SnakeSocket.sock.sendto(b'master,', SnakeSocket.ADDRESS)
                logging.warning('sendto 2 :' + str(SnakeSocket.state))
                time.sleep(0.5)
        elif SnakeSocket.state == 'master':
            # print('send master')
            pass
        elif SnakeSocket.state == 'slave':
            pass
            pass

    def recv(self):
        """
        1.从客户端接收每一步的位置。
        2.需要加锁。
        """
        logging.info('recv start')
        while 1:
            # with self.lock:
            # print(SnakeSocket.state)
            logging.warning('recvfrom 1')
            data, addr = SnakeSocket.sock.recvfrom(1024)
            logging.warning('recvfrom 2')
            # print(data, addr)
            # SnakeSocket.sock.sendto(b'2', addr)
            # sign = self.mysnake.recv(data)
            # print(SnakeSocket.state, data, addr)
            sign, ip = data.decode().rsplit(',')
            if SnakeSocket.state is None:               # 只有在初始化的时候才会执行。
                # if ip == SnakeSocket.IP:                # 随机数编号如果是自己就将获得的IP地址赋值给自己。
                #     SnakeSocket.IP = addr[0]
                # if time.time() - start > 3:             # 超过3秒没有接收到任何消息，将自己设置成master。
                #     SnakeSocket.state = 'master'
                if sign == 'refuse':                    # 接收到refuse表示已经有了master，将自己设置成slave。
                    SnakeSocket.state = 'slave'
            elif SnakeSocket.state == 'master':         # 自己是master的时候。
                # SnakeSocket.sock.sendto(b'refuse', addr)
                if sign == 'master':
                    # s = socket.socket(type=socket.SOCK_DGRAM)
                    # print('server >>> ', ip, addr)
                    logging.warning('master sendto 1')
                    SnakeSocket.sock.sendto('refuse,'.encode('utf-8'), addr)
                    logging.warning('master sendto 2 ' + '+' * 50)
                pass
            elif SnakeSocket.state == 'slave':          # 自己是slave的时候。
                print('if slave')
                pass
        pass

    pass

s = SnakeSocket()

